package com.bolt.support.spring.jpa.query;

import com.bolt.support.spring.jpa.annotation.NativeSQLConfig;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.jpa.provider.QueryExtractor;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.EntityListeners;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * Created by Administrator on 2017/8/12.
 */
public class JdbcQueryMethod extends QueryMethod {

    private final QueryExtractor extractor;
    private final Method method;

    public JdbcQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
                           QueryExtractor extractor) {

        super(method, metadata, factory);

        Assert.notNull(method, "Method must not be null!");
        Assert.notNull(extractor, "Query extractor must not be null!");

        this.method = method;
        this.extractor = extractor;
    }


   public  String getAnnotatedSqlId() {
        String queryId = getAnnotationValue("value", String.class);
        return StringUtils.hasText(queryId) ? queryId : null;
    }

    private <T> T getAnnotationValue(String attribute, Class <T> type) {
        return getMergedOrDefaultAnnotationValue(attribute, NativeSQLConfig.class, type);
    }

    private <T> T getMergedOrDefaultAnnotationValue(String attribute, Class annotationType, Class <T> targetType) {

        Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
        if (annotation == null) {
            return targetType.cast(AnnotationUtils.getDefaultValue(annotationType, attribute));
        }

        return targetType.cast(AnnotationUtils.getValue(annotation, attribute));
    }

    //EntityListeners
    protected boolean hasEntityListeners() {
        Annotation annotation = AnnotationUtils.findAnnotation(this.getReturnedObjectType(), EntityListeners.class);
        return annotation != null;
    }

    /**
     *
     * @return
     */
    public boolean isNativeSQLConfigQuery() {
        return AnnotationUtils.findAnnotation(method, NativeSQLConfig.class) != null;
    }


}
